package com.wh.accesscontrol.util;

import com.alibaba.fastjson.JSON;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Joy on 16/9/1.
 */
public class MathUtil {


    public static float point2(float f) {
        return pointN(f, 2);
    }

    public static double point2(double f) {
        return pointN(f, 2);
    }

    public static float point3(float f) {
        return pointN(f, 3);
    }

    public static double point3(double f) {
        return pointN(f, 3);
    }

    public static double pointN(double value, int n) {
        int sq = (int) Math.pow(10, n);
        return (double) (Math.round(value * sq)) / sq;
    }

    public static float pointN(float value, int n) {
        int sq = (int) Math.pow(10, n);
        return (float) (Math.round(value * sq)) / sq;
    }

    public static float parseFloat(Object s) {
        try {
            return Float.parseFloat(s.toString());
        } catch (Exception e) {
            return 0;
        }
    }

    public static Object parseString(String str) {
        return JSON.parse(str);
    }

    public static String toJson(Object o) {
        return JSON.toJSONString(o);
    }

    public static double parseDouble(Object s) {
        try {
            return Double.parseDouble(s.toString());
        } catch (Exception e) {
            return 0;
        }


    }


    public static long parseLong(Object s) {
        try {
            return Long.parseLong(s.toString());
        } catch (Exception e) {
            return 0;
        }
    }

    public static int parseInt(Object s) {
        try {
            return Integer.parseInt(s.toString());
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 求平均值
     *
     * @param list 数字列表
     * @return
     */
    public static double avg(List<Double> list) {
        double sum = 0;
        for (Double d : list) {
            if (d == null)
                continue;
            sum += d;
        }
        return sum / list.size();
    }


    public static boolean isUp(List<Double> list, double d) {
        double avg = avg(list);
        if (avg >= d)
            return false;
        return true;
    }


    public static String ret(int status, Object obj) {
        Map<String, Object> t_map = new HashMap<String, Object>();
        t_map.put("ret", obj);
        t_map.put("status", status);
        return JSON.toJSONString(t_map);
    }


    public static List stringToList(String str) {
        List<List> list = (List<List>) JSON.parse(str);
        return null == list ? new ArrayList() : list;
    }

    public static List stringToList_Map(String str) {
        List<Map> list = (List<Map>) JSON.parse(str);
        return null == list ? new ArrayList() : list;
    }


    public static List<List> allIn(int maxSize, List<List> lists) {
        List<List> all = new ArrayList<List>();
        for (int i = 0; i < maxSize; i++) {
            List<Object> objects = new ArrayList<Object>();

            for (List<Object> list : lists) {
                objects.add(list.get(i));
            }
            all.add(objects);
        }

        return all;
    }


    public static boolean isPassword(String password) {
        String regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{1,50}$";

        return password.matches(regex);
    }

    /**
     * 格式化为指定位小数的数字,返回未使用科学计数法表示的具有指定位数的字符串。
     * 该方法舍入模式：向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为向上舍入的舍入模式。
     * <pre>
     * 	"3.1415926", 1			--> 3.1
     * 	"3.1415926", 3			--> 3.142
     * 	"3.1415926", 4			--> 3.1416
     * 	"3.1415926", 6			--> 3.141593
     * 	"1234567891234567.1415926", 3	--> 1234567891234567.142
     * </pre>
     *
     * @param String类型的数字对象
     * @param precision     小数精确度总位数,如2表示两位小数
     * @return 返回数字格式化后的字符串表示形式(注意返回的字符串未使用科学计数法)
     */
    public static String keepPrecision(String number, int precision) {
        BigDecimal bg = new BigDecimal(number);
        return bg.setScale(precision, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    /**
     * 格式化为指定位小数的数字,返回未使用科学计数法表示的具有指定位数的字符串。<br>
     * 该方法舍入模式：向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为向上舍入的舍入模式。<br>
     * 如果给定的数字没有小数，则转换之后将以0填充；例如：int 123  1 --> 123.0<br>
     * <b>注意：</b>如果精度要求比较精确请使用 keepPrecision(String number, int precision)方法
     *
     * @param String类型的数字对象
     * @param precision     小数精确度总位数,如2表示两位小数
     * @return 返回数字格式化后的字符串表示形式(注意返回的字符串未使用科学计数法)
     */
    public static String keepPrecision(Number number, int precision) {
        return keepPrecision(String.valueOf(number), precision);
    }

    /**
     * 对double类型的数值保留指定位数的小数。<br>
     * 该方法舍入模式：向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为向上舍入的舍入模式。<br>
     * <b>注意：</b>如果精度要求比较精确请使用 keepPrecision(String number, int precision)方法
     *
     * @param number    要保留小数的数字
     * @param precision 小数位数
     * @return double 如果数值较大，则使用科学计数法表示
     */
    public static double keepPrecision(double number, int precision) {
        BigDecimal bg = new BigDecimal(number);
        return bg.setScale(precision, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 对float类型的数值保留指定位数的小数。<br>
     * 该方法舍入模式：向“最接近的”数字舍入，如果与两个相邻数字的距离相等，则为向上舍入的舍入模式。<br>
     * <b>注意：</b>如果精度要求比较精确请使用 keepPrecision(String number, int precision)方法
     *
     * @param number    要保留小数的数字
     * @param precision 小数位数
     * @return float 如果数值较大，则使用科学计数法表示
     */
    public static float keepPrecision(float number, int precision) {
        BigDecimal bg = new BigDecimal(number);
        return bg.setScale(precision, BigDecimal.ROUND_HALF_UP).floatValue();
    }
}
